package org.webflux.remote.client.handler;

import org.webflux.remote.client.bean.ServerInfo;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import org.webflux.remote.client.bean.MethodInfo;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class WebClientRestHandler implements RestHandler {
    private WebClient webClient;
    @Override
    public void init(ServerInfo serverInfo) {
        this.webClient = WebClient.create(serverInfo.getUrl());

    }

    @Override
    public Object invokeRest(MethodInfo methodInfo) {
        // 参数校验
        if (methodInfo == null) {
            return Mono.error(new IllegalArgumentException("MethodInfo must not be null"));
        }
        if (methodInfo.getHttpMethod() == null) {
            return Mono.error(new IllegalArgumentException("HttpMethod must not be null"));
        }
        if (methodInfo.getUrl() == null || methodInfo.getUrl().trim().isEmpty()) {
            return Mono.error(new IllegalArgumentException("Url must not be empty"));
        }
        checkWebClientInitialized();

        WebClient.RequestBodyUriSpec methodSpec = webClient.method(methodInfo.getHttpMethod());

        // 构建URI（支持路径参数和查询参数）
        methodSpec.uri(uriBuilder -> {
            if (methodInfo.getParams() != null && !methodInfo.getParams().isEmpty()) {
                return uriBuilder.path(methodInfo.getUrl())
                        .build(methodInfo.getParams());
            } else {
                return uriBuilder.path(methodInfo.getUrl())
                        .build();
            }
        });

//        // 构建URI（支持路径参数和查询参数）
//        methodSpec.uri(uriBuilder -> {
//            // 处理路径参数
//            if (methodInfo.getParams() != null) {
//                uriBuilder = uriBuilder.path(methodInfo.getUrl()).build(methodInfo.getParams());
//            } else {
//                uriBuilder = uriBuilder.path(methodInfo.getUrl());
//            }
//            // 处理查询参数（如果MethodInfo支持）
//            if (methodInfo.getQueryParams() != null && !methodInfo.getQueryParams().isEmpty()) {
//                methodInfo.getQueryParams().forEach(uriBuilder::queryParam);
//            }
//            return uriBuilder.build();
//        });

        // 设置请求体
        WebClient.ResponseSpec responseSpec;
        if (methodInfo.getBody() != null) {
            responseSpec = methodSpec
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(methodInfo.getBody(), methodInfo.getBodyElementType())
                    .accept(MediaType.APPLICATION_JSON)
                    .retrieve();
        } else {
            responseSpec = methodSpec
                    .accept(MediaType.APPLICATION_JSON)
                    .retrieve();
        }

        // 处理HTTP错误状态码
        responseSpec = responseSpec.onStatus(HttpStatus::isError, clientResponse ->
                clientResponse.bodyToMono(String.class)
                        .flatMap(errorBody -> Mono.error(
                                new WebClientResponseException(
                                        clientResponse.statusCode().value(),
                                        "Request failed with status code: " + clientResponse.statusCode(),
                                        clientResponse.headers().asHttpHeaders(),
                                        errorBody.getBytes(),
                                        null
                                )
                        ))
        );

        // 处理响应类型并统一异常处理
        if (methodInfo.isReturnFlux()) {
            return responseSpec
                    .bodyToFlux(methodInfo.getReturnElementType())
                    .onErrorResume(e -> Flux.error(convertException(e)));
        } else {
            return responseSpec
                    .bodyToMono(methodInfo.getReturnElementType())
                    .onErrorResume(e -> Mono.error(convertException(e)));
        }
    }

    // 异常转换辅助方法
    private Throwable convertException(Throwable e) {
        if (e instanceof WebClientResponseException) {
            return e;
        }
        return new RuntimeException("Remote service invocation failed: " + e.getMessage(), e);
    }


    // WebClient初始化检查
    private void checkWebClientInitialized() {
        if (this.webClient == null) {
           this.webClient = WebClient.builder().build();
        }
    }

}
